package com.LachesismStorm.lachesism.commonTools;

import java.net.Socket;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.TimeUnit;
import java.util.logging.Level;
import java.util.logging.Logger;

/**
 * @Author lachesism
 * @Date 2024-12-26 20:09
 **/
public class PortScanner {

    // 扫描的目标IP地址
    private String targetIp;
    // 扫描的端口范围
    private int startPort;
    private int endPort;
    // 设置线程池来并发扫描
    private ExecutorService executor;
    // 使用 Logger 记录日志
    private static final Logger LOGGER = Logger.getLogger(PortScanner.class.getName());

    public PortScanner(String targetIp, int startPort, int endPort) {
        this.targetIp = targetIp;
        this.startPort = startPort;
        this.endPort = endPort;
        // 初始化线程池
        this.executor = Executors.newFixedThreadPool(100); // 设置最大线程池数为100
    }

    /**
     * 执行端口扫描
     */
    public void scan() {
        // 遍历所有端口并执行扫描
        for (int port = startPort; port <= endPort; port++) {
            final int currentPort = port;  // 使 port 成为一个局部变量，它的值不会改变
            executor.submit(() -> checkPort(targetIp, currentPort));  // 使用 final 或实际上是 final 的 currentPort
        }
        // 关闭线程池
        shutdownExecutor();
    }

    /**
     * 检查单个端口是否开放
     * @param ip 目标IP
     * @param port 目标端口
     */
    private void checkPort(String ip, int port) {
        try (Socket socket = new Socket()) {
            socket.connect(new java.net.InetSocketAddress(ip, port), 1000);  // 设置连接超时1秒

            LOGGER.log(Level.INFO, "Port {0} is open on {1}", new Object[]{port, ip});
        } catch (Exception e) {
            // 端口未开放时不输出错误，避免过多日志
        }
    }

    /**
     * 优雅地关闭线程池
     */
    private void shutdownExecutor() {
        try {
            executor.shutdown();  // 阻止新的任务提交
            if (!executor.awaitTermination(60, TimeUnit.SECONDS)) {  // 等待最多60秒让任务结束
                executor.shutdownNow();  // 强制关闭未完成的任务
            }
        } catch (InterruptedException e) {
            executor.shutdownNow();
            Thread.currentThread().interrupt();  // 处理中断异常
        }
    }

    public static void main(String[] args) {
        String targetIp = "139.224.51.76"; // 输入目标IP
        int startPort = 1;                   // 扫描的起始端口
        int endPort = 10000;                 // 扫描的结束端口

        PortScanner scanner = new PortScanner(targetIp, startPort, endPort);
        scanner.scan();
    }
}
